home *** CD-ROM | disk | FTP | other *** search
/ Inside Mac Games Volume 1 / Inside Mac Games Volume 1.iso / Shareware / Arcade / Bolo 0.99.2 / Documentation / Sample Code / Standard Autopilot sample code / How to write plug-in brains < prev    next >
Encoding:
Text File  |  1993-06-08  |  14.9 KB  |  339 lines  |  [TEXT/KAHL]

  1. What are "Plug-In Brains?"
  2. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  3. Bolo 0.99 supports plug-in 'brain' modules to drive Bolo tanks, to allow:
  4. 1. One player games against a number of 'AI' tanks.
  5. 2. Two player games, where each player commands a platoon of AI tanks.
  6. 3. 'Core War' style tournaments where people compete to write the best AI
  7.    algorithms.
  8.  
  9. Sample code is provided. It is basically the original Bolo 0.96 'Autopilot'
  10. converted to BBRN format, with the addition of better path finding and mine
  11. clearing. It is not very smart.
  12.  
  13. Changes from BBRN interface version 1
  14. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  15. The new BBRN interface is version 2, which means that you must recompile
  16. with the new header file, and create your CODE resources with ID 1002.
  17.  
  18. In future versions of Bolo I plan to maintain binary compatibility back
  19. to previous BBRN formats, but there are not enough version 1 brains
  20. written (and published) to make it worth it this time.
  21.  
  22. The "obstructed" field is now called "tankobstructed", and there is a new
  23. field called "manobstructed" which indicates when the man is stuck against
  24. some obstacle.
  25.  
  26. There is a new field "carriedpills" which tells you how many pillboxes your
  27. tank is carrying. The new field "carriedbases" will always be zero in Bolo
  28. 0.99, but is provided for possible future use.
  29.  
  30. The object list now includes your own shells as well -- see the sample code
  31. for example code to determine which shells are heading TOWARDS your tank.
  32.  
  33. Bolo does not currently distinguish between shells fired BY you, from
  34. those fired AT you by pillboxes, so the only way you can tell if a shell
  35. is a threat is by what direction it is travelling.
  36.  
  37. How to write plug-in 'brain' modules to drive Bolo tanks.
  38. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  39. Each plug-in brain module is a separate file, stored in the "Brains" folder.
  40.  
  41. The file should have type 'BBRN'.
  42. It can have any creator code, although 'BOLO' is probably a sensible choice.
  43. It should contain a CODE resource with ID 1000+x, where x is the BrainInfo
  44. version that your code is compiled for (see below). For version 2 of the
  45. interface, this means that you should make your code resource have ID 1002.
  46.  
  47. When the user selects your brain from the "Tank Control" menu in Bolo, your
  48. CODE resource is loaded into memory and locked down.
  49.  
  50. Your CODE resource will be called with A4 set to point to the base address
  51. of the resource (ie set up to support Think C's A4-relative CODE resource
  52. globals). You may make limited Operating System and Toolbox calls, including
  53. QuickDraw, if necessary (eg putting up a dialog box). (However, care must be
  54. taken if you decide to access QuickDraw globals. See the Think C manual
  55. chapter on CODE resources.) Your resource file will be open if you need
  56. access to your resources. One parameter is passed on the stack with pascal
  57. calling conventions. You should declare your main routine thus:
  58.  
  59. pascal short main(const BrainInfo *info)
  60.  
  61. The structure you are passed looks like this:
  62. typedef struct
  63.     {
  64.     u_short BoloVersion;    // two hex bytes, eg. 0x0098 means version 0.98
  65.     u_short InfoVersion;    // current version of the BrainInfo structure is 1
  66.     void   *userdata;        // Initially points to address of your CODE resource
  67.     u_short padding1;        // unused at present
  68.     u_short PrefsVRefNum;
  69.     u_char *PrefsFileName;
  70.     u_short operation;        // 0=OPEN, 1=CLOSE, 2=THINK, 200+ menu
  71.     u_short menu_item;
  72.     ... // (see accompanying header files for more details)
  73.     } BrainInfo;
  74.  
  75. BoloVersion is passed for informational value only. Most Brains should
  76. not care what version of Bolo is running. You should however check that
  77. InfoVersion indicates a version of the BrainInfo structure that your code
  78. understands. If your codes does not understand the InfoVersion then you
  79. should return a non-zero error code from the "OPEN" call.
  80.  
  81. "userdata" is provided for MPW users who do not have the A4-globals facility.
  82. It is initialized to point to the start address of your code (ie the same as
  83. the value in A4), but if you elect to change its value (say to point to a
  84. block of memory you have allocated for workspace) then that value will be
  85. preserved in subsequent calls.
  86.  
  87. PrefsVRefNum and PrefsFileName are passed so that you can access the user's
  88. Bolo Preferences file if you wish, to store settings between activations of
  89. your Brain. You should store your preferences as NAMED resources in the file.
  90.  
  91. A lot more information is passed in the BrainInfo structure, although most
  92. of it will only be useful for the "THINK" call.
  93.  
  94. The operation codes.
  95. ~~~~~~~~~~~~~~~~~~~~
  96. 0: OPEN.
  97. The first call, made once, immediately after the CODE resource is loaded into
  98. memory. If you wish to offer user-configurability, you may add a menu to the
  99. menu bar. The menu ID should be 1000 or greater. If you need to use hierarchical
  100. sub-menus, you can use ids in the range 200-255. You may allocate memory for
  101. workspace, but your total memory usage (size of CODE resource plus size of
  102. extra memory allocated) must not exceed 32K. If you need more than this, you
  103. must use "MultiFinder Temporary Memory" (see Inside Macintosh VI 28-33).
  104. Return zero if initialization was successful, or non-zero if it failed
  105. (eg. insufficient memory). If non-zero is returned, your code will not be
  106. called again (not even a CLOSE message).
  107.  
  108. 1: CLOSE.
  109. Called once as the final call when the user turns off your brain. You should
  110. ensure that all allocated memory is released, all menus are removed etc.
  111.  
  112. 2: THINK.
  113. This, the most important call, is done as frequently as the load on the
  114. Macintosh will allow. Each time, information describing the current start of
  115. the world around the tank is given, and your code should decide what action to
  116. take.
  117.  
  118. 200+: MENU.
  119. Called when the user chooses an item from your menu with this menu ID number.
  120. The number of the item which was selected from the menu is given in "menu_item".
  121.  
  122. The THINK message.
  123. ~~~~~~~~~~~~~~~~~~
  124. Every time through the main event loop, Bolo will send you a THINK message.
  125. This means that you are subject to the vagaries of the Macintosh process
  126. scheduling mechanism. If another application holds the CPU for a long time, or
  127. the user performs some action which hogs the machine, then it is possible that
  128. you might not get any calls for a significant length of time. You should be
  129. aware of this limitation, and users should be aware that if they overload the
  130. machine then AI routines will not perform very well. A corollary of this is
  131. that YOU can hog the CPU for a long time if you wish. However, Bolo is a real-
  132. time game. If you spend too long deciding what to do, then your tank will have
  133. been shot and destroyed by the time you make up your mind. A good guideline is
  134. no more than a tenth of a second of thinking time per call. If you want to be
  135. very ambitious and do dynamic adjustment, you can use TickCount or the Time
  136. Manager to measure the passage of time, and return when some predetermined
  137. time has passed.
  138.  
  139. The information you are passed is basically a software interface to the
  140. information that a human player has available visually.
  141.  
  142. The maximum number of players is given because it controls the size of the
  143. player bitmap structures used for messages and alliances. It may also be
  144. useful to determine your memory allocation needs.
  145.  
  146. You are told your tank’s current position, speed, direction, whether it is
  147. on a boat etc.
  148. You are told your current tank stocks and other status information.
  149.  
  150. If newtank is non-zero it indicates that your tank was just killed, and this
  151. is new tank you are controlling. This is done so that your algorithm is not
  152. hopelessly confused to find itself suddenly on a boat out in the deep sea.
  153. Your first THINK message after the OPEN call will have this 'new tank'
  154. indication set.
  155.  
  156. If there is a friendly base within range, then its position and stocks are
  157. given. Otherwise base will be NULL.
  158.  
  159. If man_status is zero, the man is in the tank, ready for action. If man_status
  160. is one, then your man is dead and a new man is parachuting in. If man_status
  161. is any other value, then the man is outside the tank, building, in which case
  162. man_direction gives the direction of travel of the man, and (man_x, man_y)
  163. gives his current position.
  164.  
  165. If (*pillview) is non-negative, then the view you are given is centred on the
  166. pillbox with the given number. If (*pillview) is -1 then the view is centred on
  167. your tank. To change where your next view will come from, set (*pillview) to
  168. the desired value. You may attempt to view from a dead pillbox (or one you
  169. don't own) if you wish, but you will not see anything.
  170.  
  171. The array of TERRAIN squares is given as horizontal rows, from top to bottom,
  172. with the squares running left to right in each row (similar to the map file
  173. format). The map view information shows you everything within 14 squares of the
  174. tank -- ie anything a human could see by scrolling the tank view around with
  175. the cursor keys. For pillbox views, the visibility range is restricted to 7
  176. squares in every direction, as it is for humans.
  177. The bytes of the array have the values given below. The top bit of the byte
  178. will be set if the square has a mine (that you can see) on it.
  179.  
  180. typedef BYTE TERRAIN;
  181. enum
  182.     {
  183.     BUILDING=0, RIVER, SWAMP, CRATER, ROAD, FOREST, RUBBLE, GRASS,
  184.     HALFBUILDING, BOAT, DEEPSEA, REFBASE_T, PILLBOX_T,
  185.     NUM_TERRAINS,
  186.     TERRAIN_MASK = 0xF,
  187.     TERRAIN_MINE = 0x80,
  188.     };
  189.  
  190. For each object you can see, you are told its position, and some information.
  191. Your own tank is not included in the array of objects. All friendly pillboxes
  192. and bases are included in the array, even if currently beyond visual range.
  193.  
  194. typedef u_short OBJECT;
  195. enum
  196.     {
  197.     OBJECT_TANK=0,
  198.     OBJECT_SHOT,
  199.     OBJECT_PILLBOX,
  200.     OBJECT_REFBASE,
  201.     OBJECT_BUILDMAN
  202.     };
  203. #define OBJECT_HOSTILE 1
  204. #define OBJECT_OWNED 2
  205.  
  206. typedef struct
  207.     {
  208.     OBJECT object;
  209.     WORLD_X x;
  210.     WORLD_Y y;
  211.     WORD idnum;
  212.     BYTE direction;
  213.     BYTE info;
  214.     } ObjectInfo;
  215.  
  216. For tanks, pillboxes, refuelling bases, and men, an identifying number is
  217. given, which ranges from zero to the number of that kind of object minus one.
  218. One useful fact is that man number n is owned by tank number n.
  219.  
  220. For tanks and shots the approximate direction of travel is given.
  221. For pillboxes the 'direction' value gives the pillbox's current strength, in
  222. the range 0-15, as can be determined by human players looking at the graphics
  223. on the screen.
  224. For refueling bases and building men, the 'direction' value is unused.
  225.  
  226. Bit 0 of the info field (OBJECT_HOSTILE) is set if the object is hostile,
  227.       and clear if it is friendly.
  228. Bit 1 of the info field (OBJECT_OWNED) is set if the object is currently
  229.       'owned' by some player, and clear if it is neutral.
  230.  
  231. MessageInfo structure
  232. ~~~~~~~~~~~~~~~~~~~~~
  233. If a message was sent to you then the MessageInfo pointer will be non-null, and
  234. will point to a MessageInfo structure as described below.
  235.  
  236. typedef struct
  237.     {
  238.     u_short sender;
  239.     PlayerMap *receivers;
  240.     u_char *message;
  241.     } MessageInfo;
  242.  
  243. The sender field tells you which player sent the message. You may examine
  244. playernames[sender] to find out the ASCII name of that player. The receivers
  245. field points to a bit map indicating which players the message was sent to, and
  246. the text of the message is given by the message field.
  247.  
  248. Controlling the tank
  249. ~~~~~~~~~~~~~~~~~~~~
  250. Macros are provided to set bits in the BoloKeyMap structure. Each bit
  251. corresponds to a tank control -- accelerate, decelerate, turn, shoot, etc.
  252. Setting a bit in the holdkeys structure is equivalent to the user holding that
  253. key down (until you clear the bit explicitly). Setting a bit in the tapkeys
  254. structure is equivalent to the user tapping the key briefly (for about 1/12th
  255. of a second). This can be useful for things like firing a single shot.
  256.  
  257. Building Control
  258. ~~~~~~~~~~~~~~~~
  259. typedef BYTE BUILDMODE;
  260. enum
  261.     {
  262.     BUILDMODE_FARM=1, BUILDMODE_ROAD,
  263.     BUILDMODE_BUILD, BUILDMODE_PBOX, BUILDMODE_MINE
  264.     };
  265.  
  266. typedef struct
  267.     {
  268.     MAP_X x;
  269.     MAP_Y y;
  270.     BUILDMODE action;
  271.     } BuildInfo;
  272.  
  273. If the action field is zero, you may set the x and y coordinates to the
  274. location you wish to build at, and then set the action field to the operation
  275. you wish the man to perform. (IMPORTANT: You must set the coordinates BEFORE
  276. you set the action). When the man has been dispatched from the tank to do the
  277. building, the action field will be reset to zero, and you may then queue up
  278. the next action, to be performed when the man returns.
  279.  
  280. Alliances
  281. ~~~~~~~~~
  282. The field "PlayerBitMap *allies" tells you who you are currently allied to.
  283. If you are not in any alliance, then the bit corresponding to yourself will
  284. always be set, indicating an 'alliance' of one player.
  285.  
  286. The field "PlayerBitMap *wantallies" is used to control alliance membership.
  287.  
  288. If you are currently in an alliance (of more than just yourself) then on
  289. each call, "wantallies" will be initialized to your current set of allies.
  290. You have three options:
  291.  
  292. 1. Leave it unchanged.
  293. 2. Set new bits, indicating alliance invitations to other players.
  294.    (The invited players must have already requested an alliance with you
  295.    for the invitation to take effect.)
  296. 3. Set it to zero, indicating your desire to leave this alliance.   
  297.  
  298. If you are NOT currently in an alliance, then the bits indicate who you would
  299. like to be in an alliance with, should they choose to invite you. You are free
  300. to set the bits any way you please, including all zero, to indicate that you
  301. do not want an alliance with anybody. It is not necessary to set the bit for
  302. yourself -- it is assumed that you want to be friendly to yourself.
  303.  
  304. If two non-allied players both indicate a desire to be allied to each other,
  305. then a mutual alliance is automatically formed.
  306.  
  307. Sending messages
  308. ~~~~~~~~~~~~~~~~
  309. messagedest points to a bitmap of flags as described above. For each tank you
  310. want to send to, set the appropriate bit in the bitmap. If sendmessage[0] is
  311. zero then you may write a message into the buffer it points to. The message
  312. should be a pascal string -- ie sendmessage[0] will then contain the length of
  313. the string. When the message has been sent, sendmessage[0] will be reset to
  314. zero. You can send a message to yourself only for the purpose of displaying
  315. debugging messages, if necessary.
  316.  
  317. A note on types
  318. ~~~~~~~~~~~~~~~
  319. Directions are given as single bytes, with the circle divided into 256
  320. divisions. 0 is North, 64 is East, 128 is South, 192 is West, and 255 is all
  321. the way around, almost back to due North.
  322.  
  323. MAP coordinates are 8 bits each for X and Y, and the unit is one map square.
  324. 0,0 is the top left corner of the 'world', and coordinates increase downwards
  325. and to the right. 255,255 is the bottom right corner of the world. The position
  326. of pillboxes and refueling bases are given in MAP coordinates, since they are
  327. constrained to lie on map squares.
  328.  
  329. WORLD coordinates are 16 bits each for X and Y. They are a higher resolution
  330. version of MAP coordinates, used for objects such as tanks which can move on a
  331. finer grid than whole map squares. Like MAP coordinates, WORLD coordinates
  332. start with 0,0 in the top left, increasing downwards and to the right. 256
  333. WORLD coordinate units make one MAP coordinate unit, so effectively the top
  334. byte of the WORLD coordinate gives the MAP square, and the low byte gives the
  335. location within the square.
  336.  
  337. The coordinates given for objects like tanks and shots give the position of the
  338. centre of the object.
  339.